using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
using System.Drawing;
using System.Text;

using Styx;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.Common.Helpers;
using Styx.Pathing;

using CommonBehaviors.Actions;

using Singular.Dynamics;
using Singular.Helpers;
using Singular.Managers;
using Singular.Settings;

using Action = Styx.TreeSharp.Action;
//
using Rest = Singular.Helpers.Rest;
//
using LocationRetriever = Singular.Helpers.LocationRetriever;
using yoyo;

namespace Bloody
{
    public class Routine : CombatRoutine
    {
        /// <summary>
        /// The name of this CombatRoutine
        /// </summary>
        /// <value>
        /// The name.
        /// </value>
        public override string Name { get { return "Bloody2.0"; } }


        /// <summary>
        /// The <see cref="T:Styx.WoWClass"/> to be used with this routine
        /// </summary>
        /// <value>
        /// The class.
        /// </value>
        public override WoWClass Class { get { return WoWClass.DeathKnight; } }


        private Composite _combat, _buffs;

        public override bool WantButton { get { return true; } }

        public override Composite CombatBehavior { get { return _combat; } }
        public override Composite PreCombatBuffBehavior { get { return _buffs; } }
        public override Composite CombatBuffBehavior { get { return _buffs; } }

        public override void OnButtonPress()
        {
            //Logger.Write(Colors.Yellow, "Config opened!");
            yoyo.yoyoForm1 myConfig = new yoyo.yoyoForm1();
            myConfig.ShowDialog();
        }

		private bool IsTargetBoss()
        {
            if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.WorldBoss ||
               (StyxWoW.Me.CurrentTarget.Level >= 90 && StyxWoW.Me.CurrentTarget.Elite && StyxWoW.Me.CurrentTarget.MaxHealth > 10000000))
                return true;

            else return false;
        }
		
		private int addCount()
        {
            int count = 0;
            foreach (WoWUnit u in ObjectManager.GetObjectsOfType<WoWUnit>(true, true))
            {
                if (u.IsAlive
                    && StyxWoW.Me.CurrentTarget != null
                    && u.Guid != StyxWoW.Me.Guid
                    && !u.IsFriendly
                    && (u.IsHostile || u.IsNeutral)
                    && !u.IsCritter
                    && u.Location.Distance(StyxWoW.Me.Location) <= 10
                    && (u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember || u.IsTargetingMeOrPet || u.IsTargetingAnyMinion))
                {
                    count++;
                }
            }
            return count;
        }

		private int HSaddCount()
        {
            int count = 0;
            foreach (WoWUnit u in ObjectManager.GetObjectsOfType<WoWUnit>(true, true))
            {
                if (u.IsAlive
                    && StyxWoW.Me.CurrentTarget != null
                    && u.Guid != StyxWoW.Me.Guid
                    && !u.IsFriendly
                    && (u.IsHostile || u.IsNeutral)
                    && !u.IsCritter
                    && u.IsWithinMeleeRange
                    && (u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember || u.IsTargetingMeOrPet || u.IsTargetingAnyMinion))
                {
                    count++;
                }
            }
            return count;
        }

        public override void Initialize()
        {
            _combat = CreateCombat();
            _buffs = CreateBuffs();
        }


        Composite CreateBuffs()
        {
            return new PrioritySelector(
				Cast("Blood Presence", ret => !StyxWoW.Me.HasAura("Blood Presence")),
				Cast("Horn of Winter", ret => (!StyxWoW.Me.HasAura("Horn of Winter") && !StyxWoW.Me.Mounted)),
				Cast("Bone Shield", ret => (!StyxWoW.Me.HasAura("Bone Shield") && !StyxWoW.Me.Mounted)),
				new Decorator(ret =>
					!StyxWoW.Me.HasAura("Visions of Insanity"),
					new Action(abc =>
					{
						WoWItem item = StyxWoW.Me.BagItems.Find(ret => ret.Entry == 86569);
                            if (item != null) item.Use(); 
					}))
				//Cast("Crystal of Insanity", ret => (!StyxWoW.Me.HasAura("Visions of Insanity") && !StyxWoW.Me.Mounted))
			);
        }


        Composite CreateCombat()
        {
			return new Decorator ( ctz => !StyxWoW.Me.Mounted && !StyxWoW.Me.HasAura("Drink") && !StyxWoW.Me.HasAura("Food") && !StyxWoW.Me.HasAura("First Aid"),
				new PrioritySelector(
				//Movement
				new Decorator ( ctt =>!yoyoSettings.myPrefs.DisableAllMovement && !StyxWoW.Me.CurrentTarget.IsWithinMeleeRange,				
				new Action(ret => 
				{ 
                        Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
				})),
				new Action(ret => 
				{ 
                    if (!yoyoSettings.myPrefs.DisableAllMovement && StyxWoW.Me.CurrentTarget.IsWithinMeleeRange && StyxWoW.Me.IsMoving)
                    {
                        WoWMovement.MoveStop();
						//return;
                    };
					return RunStatus.Failure;
				}),
				//Facing
				new Action(ret => 
				{ 
					if (!yoyoSettings.myPrefs.DisableAllFacement)
					{
						StyxWoW.Me.CurrentTarget.Face();
					};
					return RunStatus.Failure; 
				}),

				//Movement.CreateFaceTargetBehavior(),
                //Movement.CreateMoveToLosBehavior(),				

                // Interrupt please.
                Spell.Cast("Mind Freeze", ret => StyxWoW.Me.CurrentTarget.IsCasting && StyxWoW.Me.CurrentTarget.CanInterruptCurrentSpellCast),
                Spell.Cast("Asphyxiate", ret => StyxWoW.Me.CurrentTarget.IsCasting && StyxWoW.Me.CurrentTarget.CanInterruptCurrentSpellCast && SpellManager.Spells["Mind Freeze"].Cooldown),
                Spell.Cast("Strangulate", ret => StyxWoW.Me.CurrentTarget.IsCasting && StyxWoW.Me.CurrentTarget.CanInterruptCurrentSpellCast && SpellManager.Spells["Mind Freeze"].Cooldown),

				// Defensive/Healing CD
				Spell.Cast("Bone Shield", ret => !StyxWoW.Me.HasAura("Bone Shield")),
				Spell.Cast("Icebound Fortitude", ret => StyxWoW.Me.HealthPercent < 70),
				Spell.Cast("Vampiric Blood", ret => StyxWoW.Me.HealthPercent < 90),
				Spell.Cast("Rune Tap", ret => StyxWoW.Me.HealthPercent < 85),
				Spell.Cast("Death Siphon", ret => StyxWoW.Me.HealthPercent < 75),
				Spell.Cast("Anti-Magic Shell", ret => !StyxWoW.Me.HasAura("Anti-Magic Zone") && StyxWoW.Me.HealthPercent < 70),
				Spell.CastOnGround("Anti-Magic Zone", ctx => StyxWoW.Me.Location, 
					ret => !StyxWoW.Me.HasAura("Anti-Magic Shell") && StyxWoW.Me.HealthPercent < 70),
				Spell.Cast("Empower Rune Weapon", ret => IsTargetBoss() && 
					!(StyxWoW.Me.BloodRuneCount > 0 || StyxWoW.Me.UnholyRuneCount > 0 || StyxWoW.Me.DeathRuneCount > 0 || StyxWoW.Me.FrostRuneCount > 0)),

				Spell.Cast("Empower Rune Weapon", ret => (IsTargetBoss() && 
					(StyxWoW.Me.BloodRuneCount == 0 || StyxWoW.Me.UnholyRuneCount == 0 || StyxWoW.Me.DeathRuneCount == 0 || StyxWoW.Me.FrostRuneCount == 0))),
				new Action(ret => { UseTrinkets(); return RunStatus.Failure; }),
				Spell.Cast("Blood Fury", ret => IsTargetBoss() || addCount() > 4),

				
				Spell.Cast("Outbreak", ret => !StyxWoW.Me.HasAura("Unholy Blight") &&
                                (!StyxWoW.Me.CurrentTarget.HasMyAura("Frost Fever") ||
                                !StyxWoW.Me.CurrentTarget.HasAura("Blood Plague"))),
				Spell.Cast("Icy Touch", ret => (!StyxWoW.Me.HasAura("Unholy Blight") && !StyxWoW.Me.CurrentTarget.HasMyAura("Frost Fever")) || 
					StyxWoW.Me.CurrentTarget.ActiveAuras["Frost Fever"].TimeLeft.TotalSeconds < 3),
				Spell.Cast("Plague Strike", ret => (!StyxWoW.Me.HasAura("Unholy Blight") && !StyxWoW.Me.CurrentTarget.HasAura("Blood Plague")) ||
					StyxWoW.Me.CurrentTarget.ActiveAuras["Blood Plague"].TimeLeft.TotalSeconds < 3),
 
				Spell.Cast("Death Strike", ret => !StyxWoW.Me.HasAura("Blood Shield") || 
					StyxWoW.Me.ActiveAuras["Blood Shield"].TimeLeft.TotalSeconds <= 3 ||
					StyxWoW.Me.GetAuraTimeLeft("Blood Shield", true).Seconds <= 3 ||
					StyxWoW.Me.HealthPercent <= 90),

				//new Action (ret => {Cast("Army of the Dead", ctx => StyxWoW.Me.CurrentTarget.IsBoss);return RunStatus.Failure;}),


				Spell.Cast("Dancing Rune Weapon", ret => IsTargetBoss()),// || StyxWoW.Me.CurrentRunicPower >= 70),
				Spell.Cast("Raise Dead", ret => IsTargetBoss()),
				

                // Aoe if we got more than 2 mobs to get to killing.
                //new Decorator(ret => UnfriendlyUnits.Count() >= 2,
                //   CreateAoe()),

				//AOE ================
				new Decorator( ret => HSaddCount() > 2,
					new PrioritySelector(
						Spell.Cast("Blood Boil", ret=> StyxWoW.Me.ActiveAuras.Any(u => u.Key == "Crimson Scourge")),

						//Cast("Blood Boil", ret=> StyxWoW.Me.Buffs.ContainsKey("Crimson Scourge") ||//),
						//	Me.HasActiveAura("Crimson Scourge") || StyxWoW.Me.HasAura(81141)),
						Spell.Cast("Remorseless Winter", ret => addCount() > 2),
						Spell.CastOnGround("Death and Decay", ret => StyxWoW.Me.CurrentTarget.Location, ret => addCount() > 2),
						Spell.Cast("Blood Boil", ret=> addCount() > 2 && (StyxWoW.Me.BloodRuneCount > 0 || StyxWoW.Me.DeathRuneCount > 2)),
						Spell.Cast("Rune Strike", ret => StyxWoW.Me.CurrentRunicPower >= 70),
						Spell.Cast("Death Strike"),
						Spell.Cast("Rune Strike"),
						Spell.Cast("Horn of Winter"),
						Spell.Cast("Blood Boil", ret=> StyxWoW.Me.DeathRuneCount > 1)
					)
				), //&& StyxWoW.Me.HasAura("Crimson Scourge")),
				//Cast("Heart Strike", ret => StyxWoW.Me.BloodRuneCount > 0 || HSaddCount() == 2),
				// ===================
                Spell.Cast("Soul Reaper", ret => StyxWoW.Me.CurrentTarget.HealthPercent <= 35),
                Spell.Cast("Rune Strike", ret => StyxWoW.Me.CurrentRunicPower >= 70),
				Spell.Cast("Blood Boil", ret=> StyxWoW.Me.ActiveAuras.Any(u => u.Key == "Crimson Scourge")),
				//Cast("Blood Boil", ret=> StyxWoW.Me.Buffs.ContainsKey("Crimson Scourge")),
				//Spells.Cast("Blood Boil", ret => StyxWoW.Me.HasActiveAura("Crimson Scourge")),	
				Spell.Cast("Heart Strike", ret => StyxWoW.Me.BloodRuneCount > 0 && HSaddCount() < 3),
				Spell.Cast("Rune Strike"),
 						//Cast("Icy Touch"),
						//Cast("Plague Strike"),
				Spell.Cast("Horn of Winter"),
				Spell.Cast("Death Strike")
			));
        }

        void UseTrinkets()
        {
            var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;
            var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;


            if(firstTrinket != null && CanUseEquippedItem(firstTrinket))
                firstTrinket.Use();


            if(secondTrinket != null && CanUseEquippedItem(secondTrinket))
                secondTrinket.Use();
        }

        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
                return false;


            return item.Usable && item.Cooldown <= 0;
        }


        IEnumerable<WoWUnit> UnfriendlyUnits
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => !u.IsDead && u.CanSelect && u.Attackable && !u.IsFriendly && u.IsWithinMeleeRange); }
        }

        private delegate T Selection<out T>(object context);
        Composite Cast(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret => SpellManager.Cast(spell)));
        }

        WoWPoint attackPoint
        {
            get
            {
                if (StyxWoW.Me.GotTarget)
                {
                    return WoWMovement.CalculatePointFrom(StyxWoW.Me.CurrentTarget.Location, (float)SpellManager.Spells["Death Strike"].MaxRange + 1);
                    //return WoWMovement.CalculatePointFrom(StyxWoW.Me.CurrentTarget.Location, (float)SpellManager.Spells["Auto Shot"].MaxRange - 3);
                }
                else
                {
                    WoWPoint noSpot = new WoWPoint();
                    return noSpot;
                }
            }
        }

        public static TimeSpan GetSpellCooldown(string spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Original.CooldownTimeLeft;
            }


            return TimeSpan.MaxValue;
        }
    }
}